Tinker dex 代码修复
Dex 代码的修复方案是 classloader 机制。具体原理是将修复后的 dex 文件插入到 dex 数组的最前面。
众所周知,Android 工程的 java 代码会被编译打包放在 dex 文件中。dex 结构图如下:
使用 010Editor 程序可以清晰查看 dex 文件:
dex 的 diff
dex 文件的差分采用了微信自研的 DexDiff 算法。相比 BsDiff 以文件粒度进行差分,DexDiff 算法深度利用Dex的格式来减少差异的大小,粒度更小。
dex 差分的入口是在 DexPatchGenerator 类。
|
|
executeAndSaveTo 用来生成差分包。它对 dex 各区域的数据分别进行差分:
|
|
差分工作是在 DexSectionDiffAlgorithm.java 中完成的,DexSectionDiffAlgorithm 是个抽象类,它的 execute 方法描述了差分的大致骨架,具体的实现是在各个子类完成的。骨架代码如下:
|
|
最后调用 DexPatchGenerator.java 的 writePatchOperations 方法将 patch 信息写入差分包文件中:
|
|
以字符串的 diff 过程为例, 假设老 dex 文件中字符串序列为 “c”、”a”、”d”、”e” ,新dex 文件中字符串序列为 “c”、”b”、”e”、”f”
先收集字符串序列,老字符串序列为 {0,”c”},{1,”a”},{2,”d”},{3,”e”},新字符串序列为 {0,”c”},{1,”b”},{2,”e”},{3,”f”}
排序后的序列分别为 {1,”a”},{0,”c”},{2,”d”},{3,”e”} 和 {1,”b”},{0,”c”},{2,”e”},{3,”f”}
使用指针 oldCursor、newCursor 遍历后得到的操作序列为 {OP_DEL,1}、{OP_ADD,1,”b”}、{OP_DEL,2}、{OP_ADD,3,”f”}
对操作序列进行排序和合并后得到序列: {OP_REPLACE,1,”b”}、{OP_DEL,2}、{OP_ADD,3,”f”}
将信息写入 patch 包对 StringData 区域中:
各个区域的差分信息都写入 patch 包后,生成的 patch 包格式如下:

参考链接: